#include "baseShm.h"
#include "macro.h"
#include "log.h"
#include <sys/shm.h>
#include <sys/ipc.h>

namespace daniel
{
    //根据ID值，获得已经创建完毕的共享内存
    BaseShm::BaseShm(int32_t shmKey)
    {
        m_shmId = ::shmget(shmKey, 0, 0);
        DANIEL_ASSERT2((m_shmId != -1), "shmget() failed!");
    }
    BaseShm::BaseShm(const std::string &path)
    {
        auto shmKey = ftok(path.c_str(), c_proID);
        DANIEL_ASSERT2(shmKey != -1, "ftok() failed!");
        m_shmId = ::shmget(shmKey, 0, 0);
        DANIEL_ASSERT2((m_shmId != -1), "shmget() failed!");
    }
    //创建共享内存
    BaseShm::BaseShm(int32_t shmKey, int32_t size)
    {
        // 0664是赋予共享内存的权限，和open()类似
        m_shmId = ::shmget(shmKey, size, IPC_CREAT | 0664);
        DANIEL_ASSERT2((m_shmId != -1), "shmget() failed!");
    }
    BaseShm::BaseShm(const std::string &path, int32_t size)
    {
        int32_t shmKey = ftok(path.c_str(), c_proID);
        DANIEL_ASSERT2(shmKey != -1, "ftok() failed");
        m_shmId = ::shmget(shmKey, size, IPC_CREAT | 0664);
        DANIEL_ASSERT2((m_shmId != -1), "shmget() failed!");
    }
    BaseShm::~BaseShm()
    {
    }
    // attach到进程、从进程detach，销毁；
    void *BaseShm::attachToProcess()
    {
        //最后一个参数为0，代表有读写权限；
        m_shmaddr = ::shmat(m_shmId, nullptr, 0);
        DANIEL_ASSERT2(((int64_t)m_shmaddr != -1), "shmat() failed!");
        return m_shmaddr;
    }
    void BaseShm::detachFromProcess()
    {
        int ret = ::shmdt(m_shmaddr);
        DANIEL_ASSERT2((ret != -1), "shmdt() failed!");
    }
    void BaseShm::destroyShm()
    {
        int ret = shmctl(m_shmId, IPC_RMID, nullptr);
        DANIEL_ASSERT2((ret != -1), "shmctl() destroy memory failed!");
    }
    int32_t BaseShm::getShmid() const
    {
        return m_shmId;
    }
    void *BaseShm::getShmStart() const
    {
        return m_shmaddr;
    }
}